1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32 import java.util.*;
33 import java.lang.management.*;
34 import java.lang.reflect.*;
35 import javax.management.*;
36 import javax.management.openmbean.*;
37 import com.sun.management.GarbageCollectionNotificationInfo;
38 import com.sun.management.GcInfo;
39 import java.security.AccessController;
40 import java.security.PrivilegedAction;
41 import java.lang.reflect.Field;
42
43 public class GarbageCollectionNotificationContentTest {
44 private static HashMap<String,GarbageCollectionNotificationInfo> listenerInvoked
45 = new HashMap<String,GarbageCollectionNotificationInfo>();
46 static volatile long count = 0;
47 static volatile long number = 0;
48 static Object synchronizer = new Object();
49
50 static class GcListener implements NotificationListener {
51 public void handleNotification(Notification notif, Object handback) {
52 String type = notif.getType();
53 if (type.equals(GarbageCollectionNotificationInfo.GARBAGE_COLLECTION_NOTIFICATION)) {
54 GarbageCollectionNotificationInfo gcNotif =
55 GarbageCollectionNotificationInfo.from((CompositeData) notif.getUserData());
56 String source = ((ObjectName)notif.getSource()).getCanonicalName();
57 synchronized(synchronizer) {
58 if(listenerInvoked.get(source) == null) {
59 listenerInvoked.put(((ObjectName)notif.getSource()).getCanonicalName(),gcNotif);
60 count++;
61 if(count >= number) {
62 synchronizer.notify();
63 }
64 }
65 }
66 }
67 }
68 }
69
70 public static void main(String[] args) throws Exception {
71 MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
72 final Boolean isNotificationSupported = AccessController.doPrivileged (new PrivilegedAction<Boolean>() {
73 public Boolean run() {
74 try {
75 Class cl = Class.forName("sun.management.VMManagementImpl");
76 Field f = cl.getDeclaredField("gcNotificationSupport");
77 f.setAccessible(true);
78 return f.getBoolean(null);
79 } catch(ClassNotFoundException e) {
80 return false;
81 } catch(NoSuchFieldException e) {
82 return false;
83 } catch(IllegalAccessException e) {
84 return false;
85 }
86 }
87 });
88 if(!isNotificationSupported) {
89 System.out.println("GC Notification not supported by the JVM, test skipped");
90 return;
91 }
92 final ObjectName gcMXBeanPattern =
93 new ObjectName("java.lang:type=GarbageCollector,*");
94 Set<ObjectName> names =
95 mbs.queryNames(gcMXBeanPattern, null);
96 if (names.isEmpty())
97 throw new Exception("Test incorrect: no GC MXBeans");
98 number = names.size();
99 for (ObjectName n : names) {
100 if(mbs.isInstanceOf(n,"javax.management.NotificationEmitter")) {
101 listenerInvoked.put(n.getCanonicalName(),null);
102 GcListener listener = new GcListener();
103 mbs.addNotificationListener(n, listener, null, null);
104 }
105 }
106
107 System.gc();
108
109 Object data[] = new Object[32];
110 for(int i = 0; i<100000000; i++) {
111 data[i%32] = new int[8];
112 }
113 int wakeup = 0;
114 synchronized(synchronizer) {
115 while(count != number) {
116 synchronizer.wait(10000);
117 wakeup++;
118 if(wakeup > 10)
119 break;
120 }
121 }
122 for (GarbageCollectionNotificationInfo notif : listenerInvoked.values() ) {
123 checkGarbageCollectionNotificationInfoContent(notif);
124 }
125 System.out.println("Test passed");
126 }
127
128 private static void checkGarbageCollectionNotificationInfoContent(GarbageCollectionNotificationInfo notif) throws Exception {
129 System.out.println("GC notification for "+notif.getGcName());
130 System.out.print("Action: "+notif.getGcAction());
131 System.out.println(" Cause: "+notif.getGcCause());
132 GcInfo info = notif.getGcInfo();
133 System.out.print("GC Info #" + info.getId());
134 System.out.print(" start:" + info.getStartTime());
135 System.out.print(" end:" + info.getEndTime());
136 System.out.println(" (" + info.getDuration() + "ms)");
137 Map<String, MemoryUsage> usage = info.getMemoryUsageBeforeGc();
138
139 List<String> pnames = new ArrayList<String>();
140 for (Map.Entry entry : usage.entrySet() ) {
141 String poolname = (String) entry.getKey();
142 pnames.add(poolname);
143 MemoryUsage busage = (MemoryUsage) entry.getValue();
144 MemoryUsage ausage = (MemoryUsage) info.getMemoryUsageAfterGc().get(poolname);
145 if (ausage == null) {
146 throw new RuntimeException("After Gc Memory does not exist" +
147 " for " + poolname);
148 }
149 System.out.println("Usage for pool " + poolname);
150 System.out.println(" Before GC: " + busage);
151 System.out.println(" After GC: " + ausage);
152 }
153
154
155 List<MemoryPoolMXBean> pools = ManagementFactory.getMemoryPoolMXBeans();
156 for (MemoryPoolMXBean p : pools ) {
157 if (!pnames.contains(p.getName())) {
158 throw new RuntimeException("GcInfo does not contain " +
159 "memory usage for pool " + p.getName());
160 }
161 }
162 }
163 }